package com.forum.module.blog.service.likes;

import com.alibaba.nacos.shaded.com.google.common.annotations.VisibleForTesting;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.forum.framework.common.exception.util.ServiceExceptionUtils;
import com.forum.framework.common.pojo.PageResult;
import com.forum.framework.common.util.object.BeanUtils;
import com.forum.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.forum.framework.security.core.LoginUser;
import com.forum.framework.security.core.util.SecurityUtils;
import com.forum.module.blog.controller.likes.vo.LikesPageReqVO;
import com.forum.module.blog.controller.likes.vo.LikesSavaReqVO;
import com.forum.module.blog.dal.dataobject.article.ArticleDO;
import com.forum.module.blog.dal.dataobject.comment.CommentDO;
import com.forum.module.blog.dal.dataobject.likes.LikesDO;
import com.forum.module.blog.dal.mysql.article.ArticleMapper;
import com.forum.module.blog.dal.mysql.comment.CommentMapper;
import com.forum.module.blog.dal.mysql.likes.LikesMapper;
import com.forum.module.blog.service.favorite.FavoriteService;
import com.forum.module.blog.service.notification.NotificationService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;

import static com.forum.module.system.enums.ErrorCodeConstants.*;

/**
 * 功能:
 * 作者:ouyzh
 * 日期:2025/3/2 18:33
 */
@Service
public class LikesServiceImpl extends ServiceImpl<LikesMapper, LikesDO> implements LikesService {
    private final LikesMapper likesMapper;

    private final ArticleMapper articleMapper;

    private final CommentMapper commentMapper;

    private final NotificationService notificationService;

    public LikesServiceImpl(LikesMapper likesMapper,
                            ArticleMapper articleMapper,
                            CommentMapper commentMapper,
                            NotificationService notificationService) {
        this.likesMapper = likesMapper;
        this.articleMapper = articleMapper;
        this.commentMapper = commentMapper;
        this.notificationService = notificationService;
    }

    @Override
    public PageResult<LikesDO> getLikesPage(LikesPageReqVO pageReqVO) {
        return likesMapper.selectPage(pageReqVO);
    }

    @Override
    public void deleteById(Long id) {
        // 1. 校验收藏存在
        validateLikesExists(id);

        likesMapper.deleteById(id);
    }

    @VisibleForTesting
    LikesDO validateLikesExists(Long id) {
        if (id == null) {
            return null;
        }
        LikesDO likesDO = likesMapper.selectById(id);
        if (likesDO == null) {
            throw ServiceExceptionUtils.exception(LIKES_NOT_EXISTS);
        }
        return likesDO;
    }

    @Override
    public void updateLikes(LikesSavaReqVO reqVO) {
        LikesDO updateObj = BeanUtils.toBean(reqVO, LikesDO.class);
        likesMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createLikes(LikesSavaReqVO reqVO) {
        // 参数校验
        validateRequest(reqVO);

        Long loginUserId = SecurityUtils.getLoginUserId();
        reqVO.setUserId(loginUserId);

        if (checkLikeExists(reqVO.getArticleId(), reqVO.getCommentId(), loginUserId)) {
            throw ServiceExceptionUtils.exception(LIKES_IS_EXISTS);
        }

        if (reqVO.getArticleId() != null) {
            likeArticle(reqVO.getArticleId(), loginUserId);
        } else {
            likeComment(reqVO.getCommentId(), loginUserId);
        }

        LikesDO likesDO = BeanUtils.toBean(reqVO, LikesDO.class);
        likesMapper.insert(likesDO);
        return null;
    }

    private void validateRequest(LikesSavaReqVO reqVO) {
        if (reqVO.getArticleId() == null && reqVO.getCommentId() == null) {
            throw ServiceExceptionUtils.exception(LIKES_REQUEST_IS_NOT_EXISTS, "文章ID和评论ID不能同时为空");
        }
        if (reqVO.getArticleId() != null && reqVO.getCommentId() != null) {
            throw ServiceExceptionUtils.exception(LIKES_REQUEST_IS_ALL_EXISTS, "文章ID和评论ID不能同时存在");
        }
    }

    private void likeArticle(Long articleId, Long loginUserId) {
        articleMapper.incrementLikes(articleId);

        ArticleDO articleDO = articleMapper.selectById(articleId);
        if (articleDO != null) {
            LoginUser loginUser = SecurityUtils.getLoginUser();
            assert loginUser != null;
            String message = "用户:" + loginUser.getInfo().get("nickname") + "，点赞了你的文章！";
            notificationService.sendMessage(articleDO.getUserId(), 2, message);
        }
    }

    private void likeComment(Long commentId, Long loginUserId) {
        commentMapper.incrementLikes(commentId);

        CommentDO commentDO = commentMapper.selectById(commentId);
        if (commentDO != null) {
            LoginUser loginUser = SecurityUtils.getLoginUser();
            assert loginUser != null;
            String message = "用户:" +
                    loginUser.getInfo().get("nickname") +
                    "，点赞了你的评论！";
            notificationService.sendMessage(commentDO.getUserId(), 2, message);
        }
    }

    /**
     * 检查是否已存在点赞记录
     */
    private boolean checkLikeExists(Long articleId, Long commentId, Long userId) {
        return likesMapper.exists(new LambdaQueryWrapperX<LikesDO>()
                .eqIfPresent(LikesDO::getUserId, userId)
                .eqIfPresent(LikesDO::getArticleId, articleId)
                .eqIfPresent(LikesDO::getCommentId, commentId));
    }
}
